using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using RayDen.Library.Components;
using RayDen.Library.Core.Collections;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Entity.Scene;
using RayDen.Library.Entity.SceneGraph;

namespace RayDen.Optix.Engine.Scene.Builders
{
    public class GeoDataBuilder : SceneBuilderComponentBase<GeometryGroupNode>
    {
        protected override void VisitInternal(GeometryGroupNode node)
        {
            var sceneData = (SceneGeometryInfo)SceneGraph.ResolveDataNode<SceneGeometryDataNode>(node).GetDataItem();
            this.Builder.SceneGeo = sceneData;

            int verticesCount = 0;
            var triangles = new List<TriangleDataInfo>();
            foreach (var geometryInfo in sceneData.Geometry)
            {
                var mesh = new BaseTriangleMeshInfo()
                {
                    MaterialName = geometryInfo.MaterialName,
                    MeshName = geometryInfo.Name,
                };
                this.Builder.Meshes.Add(mesh);

                var model = geometryInfo;
                var delta = 0;
                var index = 0;
                bool hasNormals = false;
                int[] ni = null;

                bool hasTexCoords = false;
                int[] ti = null;
                var startTriangle = Math.Max(0, triangles.Count);

                if (model.IndexData.Any())
                {
                    hasNormals = model.NormalIndexData != null && model.NormalIndexData.Any();
                    hasTexCoords = model.TextureIndexData != null && model.TextureIndexData.Any();
                    if (hasTexCoords)
                    {
                        if (!sceneData.TexCoords.Any())
                            hasTexCoords = false;
                        ti = model.TextureIndexData.ToArray();
                    }
                    if (hasNormals)
                    {
                        ni = model.NormalIndexData.ToArray();
                    }
                    mesh.HasNormals = hasNormals;
                    mesh.HasTexCoords = hasTexCoords;

                    for (int i = 0; i < model.IndexData.Count; i += 3)
                    {
                        index++;

                        var newTriangle = new TriangleDataInfo()
                        {
                            v0 = new MeshVertexInfo()
                            {
                                NormalIndex = hasNormals ? ni[i] - 1 : -1,
                                VertexIndex = model.IndexData[i] - delta,
                                TexCoordIndex = hasTexCoords ? ti[i] - 1 : -1
                            },
                            v1 = new MeshVertexInfo()
                            {
                                NormalIndex = hasNormals ? ni[i + 1] - 1 : -1,
                                VertexIndex = model.IndexData[i + 1] - delta,
                                TexCoordIndex = hasTexCoords ? ti[i + 1] - 1 : -1
                            },
                            v2 = new MeshVertexInfo()
                            {
                                NormalIndex = hasNormals ? ni[i + 2] - 1 : -1,
                                VertexIndex = model.IndexData[i + 2] - delta,
                                TexCoordIndex = hasTexCoords ? ti[i + 2] - 1 : -1
                            },

                        };
                        //model.IndexData[i] - delta, model.IndexData[i + 1] - delta, model.IndexData[i + 2] - delta
                        triangles.Add(newTriangle);
                        //meshIndexes.Add(extMesh);
                    }

                    //extMesh.Indexes = model.IndexBuffer.Select(item => item - (extMesh.StartVertice - 1)).ToArray();
                }
                /*
            else
            {
                for (int i = 0; i < GeoData.Vertices.Length; i += 3)
                {
                    var tri = new TriangleInfo(Array.IndexOf(GeoData.Vertices, GeoData.Vertices[i]),
                                               Array.IndexOf(GeoData.Vertices, GeoData.Vertices[i + 1]),
                                               Array.IndexOf(GeoData.Vertices, GeoData.Vertices[i + 2]));
                    triangles.Add(tri);
                    //meshIndexes.Add(extMesh);
                    index++;
                }
            }*/
                var endTriangle = triangles.Count;
                if (model.IndexData.Any())
                {
                    verticesCount += (model.IndexData.Max() - model.IndexData.Min());
                    mesh.InitMesh(model.IndexData.Min(), model.IndexData.Max(), startTriangle, endTriangle,
                        verticesCount);
                    mesh.Bounds = new AABB(model.VertexData.ToPointList());

                    //for (int n = startTriangle; n < endTriangle; n++) meshTriangleMap.Add(n, mesh);
                }
                else
                {
                    Debugger.Break();
                }
            }
            Builder.Triangles.AddRange(triangles);
        }
    }
}